# -*- coding: utf-8 -*-

import os
import sys
from contextlib import closing
import re
import base64
import jinja2
import hashlib
import simplejson
import time
import werkzeug.utils
import zbar
from PIL import Image

import openerp
from openerp import http
from openerp.http import request
from openerp.modules.registry import RegistryManager
from openerp.tools.safe_eval import safe_eval as eval
from werkzeug.datastructures import FileStorage
from openerp import tools
from datetime import datetime
from openerp import SUPERUSER_ID
import random
from openerp.addons.wechat.enterprise import WxApi, WxApplication, WxTextResponse, WxNewsResponse, WxArticle, WxLink
from openerp.addons.website_mshop.pools import ModelPool, CursorProxy, common_functions, PageProxy, _slug
from openerp.addons.wechat.enterprise import WxEmptyResponse
from weixin_enterprise import WeixinEnterprise

ISODATEFORMAT = '%Y-%m-%d'
import pysox
############################################################################################
# 微信企业号"测试应用"应用消息处理类
# 需要配置wechat.enterprise和wechat.application在data/dftg_corp_weixin.xml文件中
#


class WxAppCropTest(WeixinEnterprise):
    _app_xml_id = 'dftg_weixin.weixin_dftg_test_application'
    # def __init__(self):
    #     if self.is_initialized:
    #         return
    #     self.is_initialized = True
    #     # 取得微信应用配置
    #     db_name = request.session.db
    #     db = RegistryManager.get(db_name)
    #     ir_model_data = openerp.registry(db_name)['ir.model.data']
    #     with closing(db.cursor()) as cr:
    #         application_id = ir_model_data.xmlid_to_res_id(cr, 1, 'dftg_weixin.weixin_dftg_test_application')
    #         wechat_application = openerp.registry(db_name)['wechat.application']
    #         application = wechat_application.browse(cr, SUPERUSER_ID, application_id)
    #         permission_group_ids = application.permission_group_ids
    #         if permission_group_ids:
    #             permission_group = permission_group_ids[0]
    #             self.SECRET = permission_group.secret
    #             self.SECRET_TOKEN = application.callback_token
    #             self.ENCODING_AES_KEY = application.callback_aeskey
    #             self.APP_ID = application.application_id
    #             self.CORP_ID = application.enterprise_id.corp_id.encode("ascii")
    #     self.wxapi = WxApi(self.CORP_ID, self.SECRET)

    # 接收发送的地理消息
    def on_location_update(self, req):
        res = super(WxAppCropTest, self).on_location_update(req)

        db_name = request.session.db
        db = RegistryManager.get(db_name)
        with closing(db.cursor()) as cr:
            user_obj = db.get('res.users')
            picking_obj = db.get('stock.picking')
            user_ids = user_obj.search(cr, SUPERUSER_ID, [('oauth_uid', '=', req.FromUserName)])
            if user_ids:
                user_id = user_ids[0]
                # @正翔 需要添加一个控制来排除已经送货完成的订单
                picking_ids = picking_obj.search(cr, SUPERUSER_ID, [('delivery_user_id', '=', user_id), ('state', '=', 'done'), ('delivery_state', '=', 'shipping')])
                for picking_id in picking_ids:
                    db.get('stock.position').create(cr, SUPERUSER_ID, {
                        'picking_id': picking_id,
                        'user_id': user_id,
                        'latitude': req.Latitude,
                        'longitude': req.Longitude,
                        'accuracy': req.Precision,
                    })

            cr.commit()

        return res

    # def on_click(self, req):
    #     if req.EventKey != 'delivery_done':
    #         return super(WxAppCropTest, self).on_click(req)

    #     return WxTextResponse('OK', req)

    def on_unsubscribe(self, req):
        res = super(WxAppCropTest, self).on_unsubscribe(req)

        db = RegistryManager.get(request.session.db)
        with closing(db.cursor()) as cr:
            contacts_obj = db.get('weixin.contacts')

            try:
                contacts = contacts_obj.browse(cr, SUPERUSER_ID, int(req.FromUserName))
            except ValueError:
                return res

            if contacts.exists():
                contacts.write({'is_follow': False})

            cr.commit()

        return res

    def search_user_point(self, req):
        db = RegistryManager.get(request.session.db)
        with closing(db.cursor()) as cr:
            res_users = db.get('res.users')
            oauth_uid = req.FromUserName
            oauth_id_user_ids = res_users.search(cr, 1, [('oauth_uid', '=', oauth_uid)])
            res_users_objs = res_users.browse(cr, 1, oauth_id_user_ids)
            return "您当前积分 %s" % (str(res_users_objs.point_balance))

    # 发送文本回调

    def on_text(self, req):
        # 默认回复同样的文字
        db = RegistryManager.get(request.session.db)
        response_content = req.Content
        if req.Content == 'JFCX' or req.Content == '积分查询':
            response_content = self.search_user_point(req)
            return WxTextResponse(response_content, req)
        # 检查临时登录密码，如果找到匹配的，则写入user_id
        re_login_groups = re.match(r'D(\d+)(.*)', req.Content, re.I)
        if re_login_groups and re_login_groups.groups():
            groups = re_login_groups.groups()
            len_groups = len(groups)
            if len_groups > 0:
                temp_password = groups[0]
            if len_groups == 2:
                login = groups[1]
            db = RegistryManager.get(request.session.db)
            oauth_uid = req.FromUserName
            with closing(db.cursor()) as cr:
                weixin_session = db.get('weixin.session')
                session_ids = weixin_session.search(cr, SUPERUSER_ID, [('temp_password', '=', temp_password),
                                                                       ('check_time', '=', None)])
                if session_ids:
                    session_row = weixin_session.browse(cr, SUPERUSER_ID, session_ids[0])
                    res_users = db.get('res.users')
                    if login:
                        # oauth_id_is_admin = False
                        oauth_id_user_ids = res_users.search(cr, 1, [('oauth_uid', '=', oauth_uid)])
                        if oauth_id_user_ids:
                            oauth_id_user_id = oauth_id_user_ids[0]
                            oauth_id_is_admin = res_users.has_group(cr, oauth_id_user_id, 'base.group_erp_manager')
                            if oauth_id_is_admin:
                                user_ids = res_users.search(cr, 1, [('login', '=', login)])
                            else:
                                print u'------ 您没有权限替他人登录'
                        else:
                            print u'------ 您没有绑定账号'
                    elif oauth_uid:
                        user_ids = res_users.search(cr, 1, [('oauth_uid', '=', oauth_uid)])
                    if user_ids:
                        user = res_users.browse(cr, 1, user_ids[0])
                        session_row.write({'user_id': user_ids[0], 'oauth_uid': oauth_uid})
                        cr.commit()
                        db.get('bus.bus').sendone(cr, user_ids[0], 'weixin_login', {'sid': session_row.session_id})
                        response_content = user.name + u' 账号已确认登录'
                    else:
                        response_content = u'用户未找到，需要重新绑定账号'
                else:
                    response_content = u'请打开登录页面或者再次刷新页面'

        # 文件消息原样回复
        return WxTextResponse(response_content, req)
        # 发送给odoo bus消息测试（所有用户都会收到），暂时注释
        system_chat_message_dict=self.send_odoo_system_message(req.FromUserName,req.Content)
        with closing(db.cursor()) as cr:
            db.get('im_chat.message').post_and_send_wxm(cr, SUPERUSER_ID,system_chat_message_dict.get('user_id'),system_chat_message_dict.get('uuid'),
                                                        'message',
                                                        system_chat_message_dict.get('Content'))
        # 文件消息原样回复
        return WxTextResponse(req.Content, req)

    # 接受二维码图片测试 (用于出库单客户签收后的拍照)
    def on_image(self, req):
        db = RegistryManager.get(request.session.db)
        filename = self._generate_image_path(req.MediaId)[1]
        resutl = self.wxapi.download_media(req.MediaId, filename)

        # system_chat_message_dict = self.send_odoo_system_message(image.FromUserName, self._generate_image_path(image.MediaId)[0])
        # with closing(db.cursor()) as cr:
        #     db.get('im_chat.message').post_image_to_kf(cr,SUPERUSER_ID,image,'image',system_chat_message_dict.get('user_id')
        #                                            ,system_chat_message_dict.get('uuid'),'image',
        #                                            system_chat_message_dict.get('Content')
        #                                           )

        # create a reader
        scanner = zbar.ImageScanner()
        # configure the reader
        scanner.parse_config('enable')
        # obtain image data
        imgfile = open(filename, 'r')
        pil = Image.open(imgfile).convert('L')
        imgfile.close()
        width, height = pil.size
        raw = pil.tostring()
        # wrap image data
        image = zbar.Image(width, height, 'Y800', raw)
        # scan the image for barcodes
        scanner.scan(image)
        qr_code = None
        return_msg = u'无法识别二维码, 请重新拍照'
        # extract results
        for symbol in image:
            # do something useful with results
            if symbol.type == symbol.QRCODE:
                qr_code = str(symbol.data)
                url_sections = qr_code.split('/')
                section_count = len(url_sections)
                if section_count > 4:
                    bill_type = url_sections[section_count - 2]
                    bill_id = int(url_sections[section_count - 1])
                    if bill_type == 'picking':
                        with closing(db.cursor()) as cr:
                            res_users = db.get('res.users')
                            oauth_uid = req.FromUserName
                            oauth_id_user_ids = res_users.search(cr, 1, [('oauth_uid', '=', oauth_uid)])
                            picking_row = db.get('stock.picking').browse(cr, oauth_id_user_ids[0], bill_id)
                            if picking_row:
                                picking_row.write({'image_sign': raw})
                                return_msg = u'%s出库单签收照片已保存' % picking_row.name
                            else:
                                return_msg = u'找不到%s单据id:%s' % (bill_type, bill_id)
                    else:
                        with closing(db.cursor()) as cr:
                            res_users = db.get('res.users')
                            oauth_uid = req.FromUserName
                            oauth_id_user_ids = res_users.search(cr, 1, [('oauth_uid', '=', oauth_uid)])
                            sale_order_row = db.get('sale.order').browse(cr, oauth_id_user_ids[0], bill_id)
                            if sale_order_row:
                                #base64
                                #sale_order_row.write({'image_tally': base64.encodestring(raw)})
                                return_msg = u'%s理货单照片已保存' % sale_order_row.name
                            else:
                                return_msg = u'找不到%s单据id:%s' % (bill_type, bill_id)
                else:
                    return_msg = u'二维码数据格式错误:' + qr_code
        if not qr_code:
            os.remove(filename)
        del(image)

        return WxTextResponse(return_msg, req)

    def on_voice(self, voice):
        db = RegistryManager.get(request.session.db)
        resutl = self.wxapi.download_media(voice.MediaId, self._generate_image_path(voice.MediaId)[1])
        app = pysox.CSoxApp(self._generate_image_path(voice.MediaId)[1],
            self._generate_image_path(voice.MediaId)[1]+'.mp3', effectparams=[("vol", [b'18dB']), ])
        app.flow()
        system_chat_message_dict = self.send_odoo_system_message(voice.FromUserName, self._generate_image_path(voice.MediaId)[0]+'.mp3')
        with closing(db.cursor()) as cr:
            db.get('im_chat.message').post_image_to_kf(cr, SUPERUSER_ID, voice, 'voice',
                                                   system_chat_message_dict.get('user_id')
                                                   , system_chat_message_dict.get('uuid'), 'voice',
                                                   system_chat_message_dict.get('Content')
                                                   )
        return WxEmptyResponse()

    def _generate_image_path(self,  file):
        cr, context, pool = request.cr, request.context, request.registry
        direction = pool.get('ir.config_parameter').get_param(cr, SUPERUSER_ID, 'dftg_ext.editor_image_folder')
        if direction:
            if not os.path.exists(direction) or not os.path.isdir(direction):
                raise ValueError(u'错误，系统配置中获取到的路径不不是文件夹或不存在')
        else:
            main_direction = tools.config.filestore(cr.dbname)
            img_direction = 'weixin_media'
            first_direction = os.path.join(img_direction, datetime.now().strftime(ISODATEFORMAT))
            if not os.path.exists(os.path.join(main_direction, first_direction)):
                os.makedirs(os.path.join(main_direction, first_direction) )
            filename = os.path.join(first_direction,file)
        return  'weixin/editor_image?filename=' + filename,os.path.join(main_direction, filename)

    def send_odoo_system_message(self,FromUserName,Content):
        db = RegistryManager.get(request.session.db)
        with closing(db.cursor()) as cr:
            # user_obj = db.get('res.users')
            user_ids = db.get('weixin.contacts').browse(cr, SUPERUSER_ID, int(FromUserName))
            if user_ids:
                user_id = user_ids[0].odoo_user_id.id
                session_info = db.get('im_chat.session').session_get(cr, user_id,
                                                                     user_ids[0].partner_id.user_id.id)
                db.get('im_chat.session').update_state(cr, SUPERUSER_ID, session_info.get('uuid'), 'open', context=None)
                session_id = db.get('im_chat.session').search(cr, SUPERUSER_ID,
                                                              [('uuid', '=', session_info.get('uuid'))],
                                                              order='write_date desc')
                if session_id:
                    return {'user_id':user_id,'uuid':session_info.get('uuid'),'Content':Content}
                else:
                    return {}

    # 进入应用回调
    def on_enter_agent(self, req):
        redirect_uri = 'http://dftg.tunnel.mobi/web'
        weixin_url = self.wxapi.authorize_url(self.APP_ID, redirect_uri, state='{"db":"test", "agentid":1}')
        weixin_article = WxArticle(Title=u'客户通知',
                                   Description='有N个未处理',
                                   PicUrl='',
                                   Url=weixin_url)
        return WxNewsResponse(weixin_article, req)

    # 微信扫码回调
    def on_scancode_waitmsg(self, req):
        scan_type = req.ScanCodeInfo['ScanType']
        scan_result = req.ScanCodeInfo['ScanResult']

        url = ''
        if scan_type == 'qrcode' and scan_result[:4] == 'sid:':
            session_id = scan_result[4:]
            db_name = request.session.db
            db = RegistryManager.get(db_name)
            with closing(db.cursor()) as cr:
                res_user = db.get('res.users')
                user_ids = res_user.search(cr, 1, [('oauth_uid', '=', req.FromUserName)])
                if user_ids:
                    user_id = user_ids[0]
                    weixin_session = openerp.registry(db_name)['weixin.session']
                    session_ids = weixin_session.search(cr, SUPERUSER_ID, [('session_id', '=', session_id)])
                    if session_ids:
                        session_row = weixin_session.browse(cr, SUPERUSER_ID, session_ids[0])
                        session_row.write({'user_id': user_id, 'oauth_uid': req.FromUserName})
                        cr.commit()

        # 扫码出货事件
        if req.EventKey == 'delivery_out' and scan_type == 'barcode' and scan_result.partition(',')[0] == 'CODE_128':
            picking_name = scan_result.partition(',')[2]

            if picking_name:
                db_name = request.session.db
                db = RegistryManager.get(db_name)
                with closing(db.cursor()) as cr:
                    user_obj = db.get('res.users')
                    picking_obj = db.get('stock.picking')
                    user_ids = user_obj.search(cr, SUPERUSER_ID, [('oauth_uid', '=', req.FromUserName)])
                    picking_ids = picking_obj.search(cr, SUPERUSER_ID, [('name', '=', picking_name)])
                    if user_ids and picking_ids:
                        user_id, picking_id = user_ids[0], picking_ids[0]
                        picking = picking_obj.browse(cr, SUPERUSER_ID, picking_id)
                        if picking.picking_type_id and picking.picking_type_id.code == 'outgoing' and picking.state == 'assigned' and picking.delivery_state != 'delivery_done':
                            # 扫码出库后对出库单的操作
                            cr.execute('''
                                UPDATE stock_picking set delivery_user_id = %s, delivery_state = 'shipping', delivery_start_time = (now() at time zone 'UTC') WHERE id = %s
                            ''', (user_id, picking_id))
                            picking.do_picking_done()

                            cr.commit()
                            scan_result = '%s 扫码出库成功' % picking.name
                            url = db.get('wechat.application').get_callback_host(cr, SUPERUSER_ID) + '/weixin/delivery/success?picking_id=' + str(picking_id)
                        else:
                            scan_result = '%s 扫码出库失败, 点击查看详细情况' % picking.name
                            url = db.get('wechat.application').get_callback_host(cr, SUPERUSER_ID) + '/weixin/delivery/error?picking_id=%s&user_id=%s' % (str(picking_id), str(user_id))

        if req.EventKey == 'delivery_in' and scan_type == 'barcode' and scan_result.partition(',')[0] == 'EAN_13':
            ean13 = scan_result.partition(',')[2]
            if ean13:
                db_name = request.session.db
                db = RegistryManager.get(db_name)
                with closing(db.cursor()) as cr:
                    product_obj = db.get('product.product')
                    product_ids = product_obj.search(cr, SUPERUSER_ID, [('ean13', '=', ean13)])
                    if product_ids:
                        scan_result = '产品扫码成功，点击查看相关的入库操作'
                        url = db.get('wechat.application').get_callback_host(cr, SUPERUSER_ID) + '/weixin/delivery_in/?product_id=' + str(product_ids[0])
                    else:
                        scan_result = '抱歉，没有匹配到系统中的产品，请重新扫码'

        return WxNewsResponse(WxLink(Title=u'扫码结果',
                                     Description=scan_result,
                                     Url=url), req)
